package com.aliyun.messagemgt.web.aop;

import com.aliyun.messagemgt.common.errorcode.IErrorCode;
import com.aliyun.messagemgt.common.exceptions.BaseException;
import com.aliyun.messagemgt.common.dto.response.ResultMap;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

/**
 * Created with IDEA
 * ResultMap封装aop
 *
 * @author:zhangxingxing 0027012120
 * @date:2019/3/15
 * @time:17:41
 */
@Configuration
@Aspect
@Order(3)
public class ResultMapPackageAop {

    private static final Logger logger = LoggerFactory.getLogger(ResultMapPackageAop.class);

    /**
     * 切点为所有controller包下方法
     */
    @Pointcut("execution(public * com.aliyun.messagemgt.web.controller..*(..)) && !execution(public * com.aliyun.messagemgt.web.controller.push..*(..))")
    public void controllerPoint() {
        //空
    }

    /**
     * 将return参数修改成ResultMap格式
     * 修改返回值必须使用环绕增强
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("controllerPoint()")
    public ResultMap doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("ResultMapPackageAop before joinPoint.proceed");
        // 写了环绕增加后 不执行proceed该切点的其他方法将不能够执行
        Object object;
        // 捕获所有执行中发生的异常并打印封装
        try {
            object = joinPoint.proceed();
        } catch (BaseException e) {
            logger.error("exception in {}", joinPoint.getSignature(), e);
            IErrorCode errorCode = e.getErrorCode();
            return new ResultMap(ResultMap.ERROR, errorCode.errName());
        } catch (Exception e) {
            logger.error("exception in {}", joinPoint.getSignature(), e);
            return new ResultMap(ResultMap.ERROR, e.getMessage());
        }
        logger.info("ResultMapPackageAop after joinPoint.proceed");
        // 如果已经是 ResultMap 这种形式,不做处理直接返回
        if (object instanceof ResultMap) {
            return (ResultMap) object;
        }
        // 默认参数为 int 类型时  是操作数据库返回的修改行数,因此用该值判断是否操作成功
        // 规范不允许存在单一int值（除数据库操作的变更行数外）返回的情况
        if (object instanceof Integer) {
            int result = (int) object;
            if (result < 1) {
                // 操作失败
                return new ResultMap(ResultMap.ERROR, "操作失败！");
            } else {
                return new ResultMap(result);
            }
        }
        // 其他未知情况暂时先直接按success封装
        return ResultMap.success(object);
    }

}
